package com.flesler.componentas.core.base
{
	import com.flesler.componentas.core.Component;
	import com.flesler.componentas.core.Entity;
	import com.flesler.componentas.core.events.EntityEvent;
	
	import flash.events.EventDispatcher;
	
	public class BaseEntity extends EventDispatcher implements Entity
	{
		private var _components:Array = [];
		
		public function BaseEntity()
		{
		}
		
		// Utils
		
		private function index(component:Component):int
		{
			return _components.indexOf(component);
		}
		
		private function event(type:String, component:Component=null):void
		{
			dispatchEvent(new EntityEvent(type, component));
		}
		
		// Component collection
		
		public function isRegistered(component:Component):Boolean
		{
			return index(component) !== -1;
		}
		
		public function register(component:Component):void
		{
			if (isRegistered(component))
				return;
			
			_components.push(component);
			component.registerTo(this);
			
			event(EntityEvent.COMPONENT_ADDED, component);
		}
		
		public function unregister(component:Component):void
		{
			if (!isRegistered(component))
				return;
			
			_components.splice(index(component), 1);
			component.unregister();
			
			event(EntityEvent.COMPONENT_REMOVED, component);
			component.destroy();
		}
		
		public function getByType(type:Class):Component
		{
			for each (var component:Component in _components)
				if (component is type)
					return component;
			return null;
		}
		
		public function getAllByType(type:Class):Array
		{
			var list:Array = [];
			for each (var component:Component in _components)
				if (component is type)
					list.push(component);
			return list;
		}
		
		public function get components():Array
		{
			return _components.concat();
		}
		
		// Initializable Implementation
		
		public function initialize():void 
		{
			for each (var component:Component in _components)
				component.initialize();
				
			event(EntityEvent.INITIALIZED);
		}
		
		// Destroyable Implementation
		
		public function get isDestroyed():Boolean
		{
			return _components === null;
		}
		
		public function destroy():void 
		{
			// Inform before actually wiping all out
			event(EntityEvent.DESTROYED);
			
			for each (var component:Component in _components)
				component.destroy();
			
			_components = null;
		}
	}
}